package work.parabola.keyboardswitch.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import work.parabola.keyboardswitch.common.PlateConst;
import work.parabola.keyboardswitch.common.ResponseCode;
import work.parabola.keyboardswitch.common.ServerResponse;
import work.parabola.keyboardswitch.dao.LoginUserDoMapper;
import work.parabola.keyboardswitch.dao.PlateCellDoMapper;
import work.parabola.keyboardswitch.dao.PlateDoMapper;
import work.parabola.keyboardswitch.dao.SwitchDoMapper;
import work.parabola.keyboardswitch.pojo.UserSession;
import work.parabola.keyboardswitch.pojo.query.keyboard.KeyboardAddQuery;
import work.parabola.keyboardswitch.pojo.query.keyboard.KeyboardChooseSwitchQuery;
import work.parabola.keyboardswitch.pojo.query.keyboard.KeyboardListQuery;
import work.parabola.keyboardswitch.pojo.query.keyboard.KeyboardUpdateQuery;
import work.parabola.keyboardswitch.pojo.repository.PlateCellDo;
import work.parabola.keyboardswitch.pojo.repository.PlateDo;
import work.parabola.keyboardswitch.pojo.repository.SwitchDo;
import work.parabola.keyboardswitch.pojo.vo.keyboard.KeyboardListVo;
import work.parabola.keyboardswitch.pojo.vo.keyboard.KeyboardSwitchListVo;
import work.parabola.keyboardswitch.pojo.vo.keyboard.KeyboardTypeVo;
import work.parabola.keyboardswitch.pojo.vo.keyboard.KeyboardVo;
import work.parabola.keyboardswitch.service.IKeyboardService;
import work.parabola.keyboardswitch.util.DateTimeUtil;

import java.util.ArrayList;
import java.util.List;

@Service
public class KeyboardServiceImpl implements IKeyboardService {

    @Autowired
    private LoginUserDoMapper loginUserDoMapper;

    @Autowired
    private PlateDoMapper plateDoMapper;

    @Autowired
    private PlateCellDoMapper plateCellDoMapper;

    @Autowired
    private SwitchDoMapper switchDoMapper;

    @Override
    public ServerResponse getAdminPlateTypeList() {
        List<KeyboardTypeVo> keyboardTypeVoList = new ArrayList<>();

        for (PlateConst.PlateTypeEnum item : PlateConst.PlateTypeEnum.values()) {
            if (item.getCode() == PlateConst.PlateTypeEnum.TESTER.getCode()) {
                continue;
            }
            KeyboardTypeVo vo = new KeyboardTypeVo();
            vo.setCode(item.getCode());
            vo.setDesc(item.getDesc());
            keyboardTypeVoList.add(vo);
        }
        return ServerResponse.createBySuccess(keyboardTypeVoList);
    }

    @Override
    @Transactional
    public ServerResponse addAdminKeyboard(KeyboardAddQuery keyboardAddQuery, UserSession userSession) {
        if (keyboardAddQuery == null) {
            return ServerResponse.createByErrorCodeMessage(ResponseCode.ILLEGAL_ARGUMENT.getCode(),
                    ResponseCode.ILLEGAL_ARGUMENT.getDesc());
        }
        ServerResponse response = keyboardAddQuery.validate();
        if (!response.isSuccess()) {
            return response;
        }
        int rowCount = this.plateDoMapper.selectCountByNameUserId(keyboardAddQuery.getName(), userSession.getId());
        if (rowCount > 0) {
            return ServerResponse.createByErrorMessage("键盘名称重复");
        }
        PlateConst.PlateTypeEnum plateTypeEnum = PlateConst.PlateTypeEnum.codeOf(keyboardAddQuery.getType());

        PlateDo plateDo = new PlateDo();
        plateDo.setName(keyboardAddQuery.getName());
        plateDo.setType(keyboardAddQuery.getType());
        plateDo.setOpen(keyboardAddQuery.getOpen() ? PlateConst.PlateOpenEnum.OPEN.getCode() :
                PlateConst.PlateOpenEnum.NONOPEN.getCode());
        plateDo.setUserId(userSession.getId());

        rowCount = this.plateDoMapper.insertSelective(plateDo);
        if (rowCount == 0) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return ServerResponse.createByErrorMessage("键盘新增失败");
        }
        List<PlateCellDo> plateCellDoList = new ArrayList<>(plateTypeEnum.getNumber());
        for (int i = 0; i < plateTypeEnum.getNumber(); i++) {
            PlateCellDo plateCellDo = new PlateCellDo();
            plateCellDo.setPlateId(plateDo.getId());
            plateCellDo.setSequence(i);
            plateCellDo.setSwitchId(-1);
            plateCellDoList.add(plateCellDo);
        }
        rowCount = this.plateCellDoMapper.insertBatch(plateCellDoList);
        if (rowCount != plateTypeEnum.getNumber()) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return ServerResponse.createByErrorMessage("新增键盘失败");
        }
        return ServerResponse.createBySuccessMessage("新增键盘成功");
    }

    @Override
    public ServerResponse getAdminKeyboardInfo(KeyboardListQuery keyboardListQuery, UserSession userSession) {
        if (keyboardListQuery == null) {
            return ServerResponse.createByErrorCodeMessage(ResponseCode.ILLEGAL_ARGUMENT.getCode(),
                    ResponseCode.ILLEGAL_ARGUMENT.getDesc());
        }
        ServerResponse response = keyboardListQuery.validate();
        if (!response.isSuccess()) {
            return response;
        }
        PageHelper.startPage(keyboardListQuery.getPageNum(), keyboardListQuery.getPageSize());
        List<PlateDo> plateDoList = this.plateDoMapper.selectKeyboardByParam(
                keyboardListQuery.getSearchWord(), keyboardListQuery.getSearchType(), userSession.getId()
        );
        List<KeyboardListVo> keyboardListVoList = new ArrayList<>();
        for (PlateDo plateDo : plateDoList) {
            KeyboardListVo vo = new KeyboardListVo();
            vo.setId(plateDo.getId());
            vo.setName(plateDo.getName());
            vo.setType(PlateConst.PlateTypeEnum.codeOf(plateDo.getType()).getDesc());
            vo.setOpenDesc(PlateConst.PlateOpenEnum.codeOf(plateDo.getOpen()).getDesc());
            vo.setUserName(userSession.getName());
            vo.setCreateTime(DateTimeUtil.dateToStr(plateDo.getCreateTime(), DateTimeUtil.FULL_FORMAT));

            keyboardListVoList.add(vo);
        }
        PageInfo pageInfo = new PageInfo(plateDoList);
        pageInfo.setList(keyboardListVoList);

        return ServerResponse.createBySuccess(pageInfo);
    }

    @Override
    @Transactional
    public ServerResponse deleteAdminKeyboard(Integer id) {
        if (id == null) {
            return ServerResponse.createByErrorCodeMessage(ResponseCode.ILLEGAL_ARGUMENT.getCode(),
                    ResponseCode.ILLEGAL_ARGUMENT.getDesc());
        }
        PlateDo plateDo = this.plateDoMapper.selectByPrimaryKey(id);
        if (plateDo == null) {
            return ServerResponse.createByErrorMessage("键盘不存在，无法删除");
        }
        if (plateDo.getType().equals(PlateConst.PlateTypeEnum.TESTER.getCode())) {
            return ServerResponse.createByErrorMessage("键盘不存在，无法删除");
        }
        int rowCount = this.plateDoMapper.deleteByPrimaryKey(id);
        if (rowCount == 0) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return ServerResponse.createByErrorMessage("键盘删除失败");
        }
        PlateConst.PlateTypeEnum plateTypeEnum = PlateConst.PlateTypeEnum.codeOf(plateDo.getType());
        rowCount = this.plateCellDoMapper.deleteByPlateId(id);
        if (rowCount != plateTypeEnum.getNumber()) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return ServerResponse.createByErrorMessage("键盘删除失败");
        }
        return ServerResponse.createBySuccessMessage("删除键盘成功");
    }

    @Override
    public ServerResponse getAdminKeyboardDetailInfo(Integer id) {
        if (id == null) {
            return ServerResponse.createByErrorCodeMessage(ResponseCode.ILLEGAL_ARGUMENT.getCode(),
                    ResponseCode.ILLEGAL_ARGUMENT.getDesc());
        }
        PlateDo plateDo = this.plateDoMapper.selectByPrimaryKey(id);
        if (plateDo == null || plateDo.getType().equals(PlateConst.PlateTypeEnum.TESTER.getCode())) {
            return ServerResponse.createByErrorMessage("键盘不存在");
        }
        KeyboardVo keyboardVo = new KeyboardVo();
        keyboardVo.setId(plateDo.getId());
        keyboardVo.setName(plateDo.getName());
        keyboardVo.setType(plateDo.getType());
        keyboardVo.setTypeDesc(PlateConst.PlateTypeEnum.codeOf(plateDo.getType()).getDesc());
        keyboardVo.setOpen(PlateConst.PlateOpenEnum.codeOf(plateDo.getOpen()) == PlateConst.PlateOpenEnum.OPEN ?
                true : false);
        keyboardVo.setUserName(this.loginUserDoMapper.selectByPrimaryKey(plateDo.getUserId()).getName());
        keyboardVo.setCreateTime(DateTimeUtil.dateToStr(plateDo.getCreateTime(), DateTimeUtil.FULL_FORMAT));

        return ServerResponse.createBySuccess(keyboardVo);
    }

    @Override
    public ServerResponse updateAdminKeyboard(KeyboardUpdateQuery keyboardUpdateQuery) {
        if (keyboardUpdateQuery == null) {
            return ServerResponse.createByErrorCodeMessage(ResponseCode.ILLEGAL_ARGUMENT.getCode(),
                    ResponseCode.ILLEGAL_ARGUMENT.getDesc());
        }
        ServerResponse response = keyboardUpdateQuery.validate();
        if (!response.isSuccess()) {
            return response;
        }
        PlateDo plateDo = this.plateDoMapper.selectByPrimaryKey(keyboardUpdateQuery.getId());
        if (plateDo == null || PlateConst.PlateTypeEnum.codeOf(plateDo.getType()) == PlateConst.PlateTypeEnum.TESTER) {
            return ServerResponse.createByErrorMessage("键盘不存在");
        }
        PlateDo updateRecord = new PlateDo();
        updateRecord.setId(plateDo.getId());
        updateRecord.setName(keyboardUpdateQuery.getName());
        updateRecord.setOpen(keyboardUpdateQuery.getOpen() ? PlateConst.PlateOpenEnum.OPEN.getCode() :
                PlateConst.PlateOpenEnum.NONOPEN.getCode());
        int rowCount = this.plateDoMapper.updateByPrimaryKeySelective(updateRecord);
        if (rowCount == 0) {
            return ServerResponse.createByErrorMessage("更新键盘信息失败");
        }
        return ServerResponse.createBySuccessMessage("修改成功");
    }

    @Override
    public ServerResponse getAdminKeyboardSwitchList(Integer id) {
        if (id == null) {
            return ServerResponse.createByErrorCodeMessage(ResponseCode.ILLEGAL_ARGUMENT.getCode(),
                    ResponseCode.ILLEGAL_ARGUMENT.getDesc());
        }
        PlateDo plateDo = this.plateDoMapper.selectByPrimaryKey(id);
        if (plateDo == null || PlateConst.PlateTypeEnum.codeOf(plateDo.getType()) == PlateConst.PlateTypeEnum.TESTER) {
            return ServerResponse.createByErrorMessage("键盘不存在");
        }
        List<PlateCellDo> plateCellDoList = this.plateCellDoMapper.selectByPlateId(id);
        List<KeyboardSwitchListVo> keyboardSwitchListVoList = new ArrayList<>(plateCellDoList.size());
        for (PlateCellDo plateCellDo : plateCellDoList) {
            KeyboardSwitchListVo vo = new KeyboardSwitchListVo();
            vo.setCellId(plateCellDo.getId());
            vo.setSequence(plateCellDo.getSequence());
            vo.setSwitchId(plateCellDo.getSwitchId());
            if (plateCellDo.getSwitchId().equals(-1)) {
                vo.setSimpleName("轴体未选择");
                vo.setBackgroundColor("ffffff");
                vo.setColor("000000");
            } else {
                SwitchDo switchDo = this.switchDoMapper.selectByPrimaryKey(plateCellDo.getSwitchId());
                vo.setSimpleName(switchDo.getSimpleName());
                vo.setBackgroundColor(switchDo.getBackgroundColor());
                vo.setColor(switchDo.getColor());
            }

            keyboardSwitchListVoList.add(vo);
        }
        return ServerResponse.createBySuccess(keyboardSwitchListVoList);
    }

    @Override
    public ServerResponse chooseAdminKeyboardSwitch(KeyboardChooseSwitchQuery keyboardChooseSwitchQuery) {
        if (keyboardChooseSwitchQuery == null) {
            return ServerResponse.createByErrorCodeMessage(ResponseCode.ILLEGAL_ARGUMENT.getCode(),
                    ResponseCode.ILLEGAL_ARGUMENT.getDesc());
        }
        ServerResponse response = keyboardChooseSwitchQuery.validate();
        if (!response.isSuccess()) {
            return response;
        }
        SwitchDo switchDo = this.switchDoMapper.selectByPrimaryKey(keyboardChooseSwitchQuery.getSwitchId());
        if (switchDo == null) {
            return ServerResponse.createByErrorMessage("轴体不存在");
        }
        PlateCellDo plateCellDo = new PlateCellDo();
        plateCellDo.setId(keyboardChooseSwitchQuery.getCellId());
        plateCellDo.setSwitchId(keyboardChooseSwitchQuery.getSwitchId());
        int rowCount = this.plateCellDoMapper.updateByPrimaryKeySelective(plateCellDo);
        if (rowCount == 0) {
            return ServerResponse.createByErrorMessage("轴体设置失败");
        }
        return ServerResponse.createBySuccessMessage("轴体设置成功");
    }

    @Override
    @Transactional
    public ServerResponse applyAdminAllKeyboardSwitch(Integer id) {
        if (id == null) {
            return ServerResponse.createByErrorCodeMessage(ResponseCode.ILLEGAL_ARGUMENT.getCode(),
                    ResponseCode.ILLEGAL_ARGUMENT.getDesc());
        }
        PlateDo plateDo = this.plateDoMapper.selectByPrimaryKey(id);
        if (plateDo == null) {
            return ServerResponse.createByErrorMessage("键盘不存在");
        }
        if (plateDo.getType().equals(PlateConst.PlateTypeEnum.TESTER.getCode())) {
            return ServerResponse.createByErrorMessage("键盘不存在");
        }
        List<PlateCellDo> plateCellDoList = this.plateCellDoMapper.selectByPlateId(id);
        Integer switchId = null;
        for (PlateCellDo plateCellDo : plateCellDoList) {
            if (plateCellDo.getSwitchId() == null || plateCellDo.getSwitchId().equals(-1)) {
                continue;
            } else {
                switchId = plateCellDo.getSwitchId();
                break;
            }
        }
        if(switchId == null){
            return ServerResponse.createByErrorMessage("键盘未选择轴体，请至少选择一个轴体");
        }
        for(PlateCellDo plateCellDo: plateCellDoList){
            plateCellDo.setSwitchId(switchId);
            int rowCount = this.plateCellDoMapper.updateByPrimaryKeySelective(plateCellDo);
            if(rowCount == 0){
                return ServerResponse.createByErrorMessage("键盘应用所有轴体失败");
            }
        }
        return ServerResponse.createBySuccessMessage("应用键盘轴体成功");
    }
}
